/**
 * 
 */
package com.fita.wechat.web.resolver;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.util.WebUtils;

import com.fita.entity.agent.Agent;
import com.fita.wechat.Constant;
import com.fita.wechat.entity.security.Login;
import com.fita.wechat.service.AgentService;

/**
 * 
 * @author lute
 *
 */
public class SecurityArgumentResolver implements HandlerMethodArgumentResolver {

    private static final Logger logger = LoggerFactory.getLogger(SecurityArgumentResolver.class);
    
    private String mobileKey = Constant.MOBILE_KEY;
    
    private String openidKey = Constant.OPENID_KEY;
    
    @Autowired
    private AgentService agentService;
    
    /**
     * 
     * @param mobileKey
     */
    public void setMobileKey(String mobileKey) {
        this.mobileKey = mobileKey;
    }
    
    /* (non-Javadoc)
     * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
     */
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Secure.class);
    }

    /* (non-Javadoc)
     * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
     */
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        
        Secure secure = parameter.getParameterAnnotation(Secure.class);
        
        if (StringUtils.isNotBlank(secure.value())) {
            this.mobileKey = secure.value();
        }
        
        logger.trace("#resolveArgument() - Get unionid key [{}].", mobileKey);
        
        // Transform NativeWebRequest to HttpServletRequest
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        
        // Get cookie
        Cookie openidCookie = WebUtils.getCookie(request, openidKey);
        Cookie mobileCookie = WebUtils.getCookie(request, mobileKey);
        
        logger.trace("#resolveArgument() - Get unionid cookie by unionidKey [{}].", mobileKey);
        
        if (openidCookie != null) {
            
            String openid = openidCookie.getValue();
            
            logger.trace("#resolveArgument() - Get openid cookie success ======== OPENID COOKIE VALUE IS [{}].", openid);
            
            // Load agent
            Agent agent = agentService.loadByOpenid(openid);
            
            // Return user when there's no property in secure annotation
            if (agent != null && parameter.getParameterType().isAssignableFrom(Login.class)) {
                logger.trace("#resolveArgument() - Load user by openid [{}] and user id is [{}].", openid, agent.getId());
                Login login = new Login(agent);
                login.init(openid);
                return login;
            }
            
            logger.trace("#resolveArgument() - Load user by openid [{}] failed.", openid);
            
        } else if (openidCookie == null && mobileCookie != null) {
            
            String mobile = mobileCookie.getValue();
            
            logger.trace("#resolveArgument() - Get unionid cookie success ======== UNIONID COOKIE VALUE IS [{}].", mobile);
            
            // Load agent
            Agent agent = agentService.loadByMobile(mobile);
            
            // Return user when there's no property in secure annotation
            if (agent != null && parameter.getParameterType().isAssignableFrom(Login.class)) {
                logger.trace("#resolveArgument() - Load user by mobile [{}] and user id is [{}].", mobile, agent.getId());
                Login login = new Login(agent);
                return login;
            }
            
            logger.trace("#resolveArgument() - Load user by unionid [{}] failed.", mobile);
            
        }else {
            
            logger.trace("#resolveArgument() - Get unionid cookie failed ======== MOBILE UNIONID NOT EXIT.");
        }
        
        return null;
        
    }

}
